#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory>
#include <functional>
#include "Common.hpp"
#include "Connection.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"

using namespace std;
using namespace LogModule;

#define SIZE 1024
// 普通文件描述符的IO
class Channel : public Connection
{
public:
    Channel(int sockfd, InetAddr &client)
        : _sockfd(sockfd), _client_addr(client)
    {
        SetNonBlock(sockfd);
    }
    void Recver() override // 收客户端数据
    {
        char buffer[SIZE];
        while (true)
        {
            buffer[0] = 0;
            ssize_t n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if (n == 0) // 读到数据为0
            {
                EXcepter(); // 进入异常处理
                return;
            }
            else // 读取失败
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    EXcepter();
                    return;
                }
            }
        }
        LOG(LogLevel::DEBUG) << "Channel inbuffer->" << _inbuffer;
        if (!_inbuffer.empty())
        {
            _outbuffer = _handler(_inbuffer); // 处理完的数据给outbuffer
        }

        if (!_outbuffer.empty()) // 发数据
        {
            Sender();
        }
    }

    void Sender() override
    {
        while (true)
        {
            ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
            if (n > 0)
            {
                _outbuffer.erase(0, n); //发送缓冲区收到多少数据就清空多少个
                if (_outbuffer.empty())
                    break;
            }
            else if (n == 0)
            {
                break;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    EXcepter();
                    return;
                }
            }
        }
        //注意什么时候可以设置关系写事件，写事件默认就是就绪的只有当发送缓冲区数据满了的时候才设置关系写事件
        //发送缓冲区已经满了，outbuffer的数据发不到发送缓冲区中了,所以判断outbuffer不为空  
        //这时候就要关系写事件，什么时候发送缓冲区有空位了outbuffer再往发送缓冲区中写
        if (!_outbuffer.empty())
        {
            GetOwner()->EnableReadWrite(_sockfd,true,true);
        }
        else
        {
            GetOwner()->EnableReadWrite(_sockfd,true,false);
        }
    }

    void EXcepter() override    //异常处理
    {
        GetOwner()->DelConnection(_sockfd);
    }
    int GetSockFd() override // 获取文件描述符
    {
        return _sockfd;
    }
    ~Channel()
    {
    }

private:
    int _sockfd; // 套接字
    string _inbuffer;
    string _outbuffer;
    InetAddr _client_addr;
};